package com.sunchangming.myweb;

import java.sql.DriverManager;

import org.apache.log4j.Logger;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.auth.oauth2.CredentialStore;
import com.thoughtworks.xstream.XStream;

public class MySQLCredentialStore implements CredentialStore {
	private final static Logger logger = Logger
			.getLogger(MySQLCredentialStore.class);

	/** Persistence manager factory. */
	private final MySQLConfig mySQLConfig;

	/**
	 * @param persistenceManagerFactory
	 *            persistence manager factory
	 */
	public MySQLCredentialStore(MySQLConfig config) {
		this.mySQLConfig = config;
	}

	static {
		try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();
		} catch (Exception ex) {
			logger.error("err", ex);
		}
	}

	private volatile static MySQLCredentialStore instance;

	public static MySQLCredentialStore getInstance() {
		if (instance == null) {
			synchronized (MySQLCredentialStore.class) {
				if (instance == null)
					instance = new MySQLCredentialStore((MySQLConfig)(new XStream()).fromXML(new java.io.File("mysqlconfig.xml")));
			}
		}
		return instance;
	}

	public void store(String userId, Credential credential) {
		java.sql.Connection conn;
		try {
			conn = DriverManager.getConnection(mySQLConfig.url,
					mySQLConfig.username, mySQLConfig.password);
		} catch (Exception ex) {
			throw new RuntimeException("conn", ex);
		}
		java.sql.PreparedStatement stmt = null;
		try {
			stmt = conn
					.prepareStatement("insert into credential (`USERID`,`ACCESSTOKEN` ,`EXPIRATIONTIMEMILLIS`,`REFRESHTOKEN`) values (?,?,?,?)" +
							"ON DUPLICATE KEY UPDATE `ACCESSTOKEN`=?, `EXPIRATIONTIMEMILLIS`=?,`REFRESHTOKEN`=?");
			stmt.setString(1, userId);
			stmt.setString(2, credential.getAccessToken());
			stmt.setLong(3, credential.getExpirationTimeMilliseconds());
			stmt.setString(4, credential.getRefreshToken());
			stmt.setString(5, credential.getAccessToken());
			stmt.setLong(6, credential.getExpirationTimeMilliseconds());
			stmt.setString(7, credential.getRefreshToken());
			stmt.executeUpdate();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {
				stmt.close();
			} catch (java.sql.SQLException ex) {
				logger.error("err", ex);
			}
			try {
				conn.close();
			} catch (java.sql.SQLException ex) {
				logger.error("err", ex);
			}
		}
	}

	public void delete(String userId, Credential credential) {
		java.sql.Connection conn;
		try {
			conn = DriverManager.getConnection(mySQLConfig.url,
					mySQLConfig.username, mySQLConfig.password);
		} catch (Exception ex) {
			throw new RuntimeException("conn", ex);
		}
		java.sql.PreparedStatement stmt = null;
		try {
			stmt = conn
					.prepareStatement("delete from credential where `USERID` = ? ");
			stmt.setString(1, userId);
			stmt.executeUpdate();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {
				stmt.close();
			} catch (java.sql.SQLException ex) {
				logger.error("err", ex);
			}
			try {
				conn.close();
			} catch (java.sql.SQLException ex) {
				logger.error("err", ex);
			}
		}
	}

	public boolean load(String userId, Credential credential) {
		java.sql.Connection conn;
		try {
			conn = DriverManager.getConnection(mySQLConfig.url,
					mySQLConfig.username, mySQLConfig.password);
		} catch (Exception ex) {
			throw new RuntimeException("conn", ex);
		}
		java.sql.PreparedStatement stmt = null;
		java.sql.ResultSet rs = null;
		try {
			stmt = conn
					.prepareStatement("select `USERID`,`ACCESSTOKEN` ,`EXPIRATIONTIMEMILLIS`,`REFRESHTOKEN` from  credential where USERID=?");
			stmt.setString(1, userId);
			rs = stmt.executeQuery();
			if (!rs.next())
				return false;
			credential.setAccessToken(rs.getString("ACCESSTOKEN"));
			credential.setExpiresInSeconds(rs.getLong("EXPIRATIONTIMEMILLIS"));
			credential.setRefreshToken(rs.getString("REFRESHTOKEN"));
			return true;
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if (rs != null) {
				try {
					rs.close();
				} catch (java.sql.SQLException ex) {
					logger.error("err", ex);
				} // ignore

				rs = null;
			}

			try {
				if (stmt != null)
					stmt.close();
			} catch (java.sql.SQLException ex) {
				logger.error("err", ex);
			}
			try {
				conn.close();
			} catch (java.sql.SQLException ex) {
				logger.error("err", ex);
			}
		}
		return false;
	}
}